博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
qml demo分析(rssnews-常见新闻布局)
阅读量:6994 次
发布时间:2019-06-27

本文共 7704 字,大约阅读时间需要 25 分钟。

一、效果展示

  今儿来分析一篇常见的ui布局,完全使用qml编写,ui交互效果友好,如图1所示,是一个常见的客户端新闻展示效果,左侧是一个列表,右侧是新闻详情。

图1 新闻效果图

二、源码分析

  首先先来总体分析下该示例代码的工程目录,如图2所示,总共有6个qml文件。其中BusyIndicator和ScrollBar组件是qml已经存在的组件,NewsDelegate组件是新闻详情页中的一项,CategoryDelegate组件是左侧列表中的一项,RssFeeds组件是左侧新闻列表数据源,rssnews文件是主程序文件。

图2 工程目录

  结合图1看程序工程目录,是不是觉着一目了然。NewsDelegate组件和CategoryDelegate组件是两个绘制代理,RssFeeds组件提供一个视图数据源,其中还有一个视图的数据源在rssnews.qml文件内部定义。接下来我主要分析下主程序文件rssnews.qml和NewsDelegate绘制代理

1、主程序文件

  主程序文件代码如下,程序中关键的地方都有注释,相比于之前的文章注释少了许多,大多都是一些常见的属性没有了注释。

1 import QtQuick 2.2  2 import QtQuick.XmlListModel 2.0  3 import QtQuick.Window 2.1  4 import "./content"  5   6 Rectangle {  7     id: window  8   9     width: 800 10     height: 480 11  12     property string currentFeed: rssFeeds.get(0).feed//get方法为ListModel内置方法,返回指定索引item 13     property bool loading: feedModel.status === XmlListModel.Loading//是否是加载中。。。 14     property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation 15  16     onLoadingChanged: { 17         if (feedModel.status == XmlListModel.Ready) 18             list.positionViewAtBeginning() 19     } 20  21     RssFeeds { id: rssFeeds } 22  23     XmlListModel { 24         id: feedModel 25  26         source: "http://" + window.currentFeed 27         query: "/rss/channel/item[child::media:content]" 28         namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';" 29  30         XmlRole { name: "title"; query: "title/string()" } 31         // Remove any links from the description 32         XmlRole { name: "description"; query: "fn:replace(description/string(), '\<a href=.*\/a\>', '')" } 33         XmlRole { name: "image"; query: "media:content/@url/string()" } 34         XmlRole { name: "link"; query: "link/string()" } 35         XmlRole { name: "pubDate"; query: "pubDate/string()" } 36     } 37  38     ListView {
//左侧新闻列表 39 id: categories 40 property int itemWidth: 190 41 42 width: isPortrait ? parent.width : itemWidth 43 height: isPortrait ? itemWidth : parent.height 44 orientation: isPortrait ? ListView.Horizontal : ListView.Vertical 45 anchors.top: parent.top 46 model: rssFeeds 47 delegate: CategoryDelegate { itemSize: categories.itemWidth } 48 spacing: 3 49 } 50 51 ScrollBar { 52 id: listScrollBar 53 54 orientation: isPortrait ? Qt.Horizontal : Qt.Vertical 55 height: isPortrait ? 8 : categories.height; 56 width: isPortrait ? categories.width : 8 57 scrollArea: categories;//关联滚动的区域 58 anchors.right: categories.right//锚点定位 59 } 60 61 ListView {
//右侧新闻详情 由多个项NewsDelegate组成 62 id: list 63 64 anchors.left: isPortrait ? window.left : categories.right 65 anchors.right: closeButton.left 66 anchors.top: isPortrait ? categories.bottom : window.top 67 anchors.bottom: window.bottom 68 anchors.leftMargin: 30 69 anchors.rightMargin: 4 70 clip: isPortrait 71 model: feedModel 72 footer: footerText//页脚 视图最底部的修饰 73 delegate: NewsDelegate {} 74 } 75 76 ScrollBar { 77 scrollArea: list 78 width: 8 79 anchors.right: window.right 80 anchors.top: isPortrait ? categories.bottom : window.top 81 anchors.bottom: window.bottom 82 } 83 84 Component { 85 id: footerText 86 87 Rectangle { 88 width: parent.width 89 height: closeButton.height 90 color: "lightgray" 91 92 Text { 93 text: "RSS Feed from Yahoo News" 94 anchors.centerIn: parent 95 font.pixelSize: 14 96 } 97 } 98 } 99 100 Image {
//关闭按钮 点击退出程序101 id: closeButton102 source: "content/images/btn_close.png"103 scale: 0.8104 anchors.top: parent.top105 anchors.right: parent.right106 anchors.margins: 4107 opacity: (isPortrait && categories.moving) ? 0.2 : 1.0108 Behavior on opacity {109 NumberAnimation { duration: 300; easing.type: Easing.OutSine }110 }111 112 MouseArea {113 anchors.fill: parent114 onClicked: {115 Qt.quit()116 }117 }118 }119 }

  footer属性指定页脚,就像word文件的页脚一样,位于ListView最低端,如图1中第一帧的RSS Feed from Yahoo News字段,其实每个页面都有这个字段,只是都位于ListView内容最低端。

2、新闻详情页中项

  如图1所示,该NewsDelegate绘制代理是右侧页面中的一条新闻项,右侧页面是一个ListView,内部有许多项组成,每一项都是由该代理绘制。

1 //新闻详情中的一条 2 import QtQuick 2.2 3  4 Column { 5     id: delegate 6     width: delegate.ListView.view.width 7     spacing: 8 8  9     // Returns a string representing how long ago an event occurred10     function timeSinceEvent(pubDate) {11         var result = pubDate;12 13         // We need to modify the pubDate read from the RSS feed14         // so the JavaScript Date object can interpret it15         var d = pubDate.replace(',','').split(' ');16         if (d.length != 6)17             return result;18 19         var date = new Date([d[0], d[2], d[1], d[3], d[4], 'GMT' + d[5]].join(' '));20 21         if (!isNaN(date.getDate())) {22             var age = new Date() - date;23             var minutes = Math.floor(Number(age) / 60000);24             if (minutes < 1440) {25                 if (minutes < 2)26                     result = qsTr("Just now");27                 else if (minutes < 60)28                     result = '' + minutes + ' ' + qsTr("minutes ago")29                 else if (minutes < 120)30                     result = qsTr("1 hour ago");31                 else32                     result = '' + Math.floor(minutes/60) + ' ' + qsTr("hours ago");33             }34             else {35                 result = date.toDateString();36             }37         }38         return result;39     }40 41     Item { height: 8; width: delegate.width }42 43     Row {44         width: parent.width45         spacing: 846 47         Column {48             Item {
//占位49 width: 450 height: titleText.font.pixelSize / 451 }52 53 Image {54 id: titleImage55 source: image//image对应模型中的字段56 }57 }58 59 Text {60 id: titleText61 62 text: title//image对应模型中的字段63 width: delegate.width - titleImage.width64 wrapMode: Text.WordWrap65 font.pixelSize: 2666 font.bold: true67 }68 }69 70 Text {
//距离新闻发布时间+带有link字样的超链接71 width: delegate.width72 font.pixelSize: 1273 textFormat: Text.RichText74 font.italic: true75 text: timeSinceEvent(pubDate) + " (Link)"76 onLinkActivated: {77 Qt.openUrlExternally(link)//link对应模型中的字段78 }79 }80 81 Text {82 id: descriptionText83 84 text: description//对应模型中的字段85 width: parent.width86 wrapMode: Text.WordWrap//换行模式 字不能拆分87 font.pixelSize: 14//字号88 textFormat: Text.StyledText//支持一些基本的文本样式标记89 horizontalAlignment: Qt.AlignLeft//水平靠左90 }91 }

三、小节

  看了有一些qml示例代码,也一直主要在分析qml代码,本小节插播一段个人总结吧,也算是小小感慨下。

  不同于以往的QWidget窗口程序,qml写界面非常简洁,从以往的示例中就能感觉的到,在友好交互方面qml比QWidget做的好,比如List下拉到头时的弹簧效果、完美的加载中展示和远程图片加载等等。qml是声明性语言,即不在像C++那样需要编译后才能运行,在代码编写时只需要关注ui,可以根据需要自己封装组件,把需要外界使用的属性使用导出的方式暴露给外界,每一个组件属性都有OnPropertyChanged槽,当属性发生变化时该槽随即执行。

  可能是由于一直从事C++相关的工作,没有声明性语言的基础,在阅读qml代码时总是感觉有一种代码散乱无处整理的感觉,现在小小的示例代码亦是如此,等到正真做起项目来不知道会是怎样一番场景。比如说绘制代理在访问一些属性时,直接访问的是模型中的字段,如果字段名称写错,这种错误只能到运行时异常后才能慢慢排查,类似于这样的代码其实有很多,突然之间就跳出一句无厘头的代码,这在C++中根本不可能出现。。。呵呵呵。。。

转载于:https://www.cnblogs.com/swarmbees/p/6550448.html

你可能感兴趣的文章
Java keyword具体解释
查看>>
如何在CentOS或者RHEL上启用Nux Dextop仓库 安装shutter截图工具
查看>>
Atitit. 注册表操作查询 修改 api与工具总结 java c# php js python 病毒木马的原理
查看>>
Asp.net MVC 的八个扩展点
查看>>
配置javaBean
查看>>
ServiceStack 概念参考文摘
查看>>
[Ogre][地形][原创]基于OgreTerrain的地形实现
查看>>
shell登录模式及其相应配置文件(转)
查看>>
Puppet常识梳理
查看>>
web.config配置文件中的configSource属性
查看>>
发现一个国内牛逼的maven仓库,速度真的太快了
查看>>
浏览器的重绘与重排
查看>>
Snmp配置
查看>>
使用java实现CNN的实战
查看>>
大白话系列之C#委托与事件讲解(二)
查看>>
linux下使用 du查看某个文件或目录占用磁盘空间的大小
查看>>
iCheck表单美化插件使用方法详解(含参数、事件等)
查看>>
IOS UIAlertController 使用方法
查看>>
深入理解闭包系列第五篇——闭包的10种形式
查看>>
JS之innerHTML,innerText,outerHTML,textContent的用法与区别
查看>>